/***************************************************
> Copyright (C) 2024 ==KINGYI== All rights reserved.
> File Name: server.c
> Author:cjy
> Mail: 
> Created Time: 2024年08月15日 星期四 15时21分58秒
***************************************************/
// 开发一个多线程计算服务器
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "cJSON.h"
#include <pthread.h>

struct data {
    int type;
    char count[10];
    float num1;
    float num2;
};

struct number {
    float sum;
};

void *fun(void *arg) {
    int listenfd = *(int *)arg;
    int ret;
    char buf[1024] = {0};
    char *dest;

    while (1) {
        ret = recv(listenfd, buf, sizeof(buf) - 1, 0);
        if (ret == -1) {
            perror("recv");
            break;
        }
        puts(buf);

        cJSON *json = NULL;
        struct data dat;
        memset(&dat, 0, sizeof(dat));

        struct number num;
        memset(&num, 0, sizeof(num));

        json = cJSON_Parse(buf);

        cJSON *node = NULL;

        node = cJSON_GetObjectItem(json, "type");
        if (node == NULL) {
            printf("can't find type\n");
            exit(-1);
        }
        if (node->type == cJSON_Number) {
            dat.type = node->valueint;
        }

        node = cJSON_GetObjectItem(json, "count");
        if (node == NULL) {
            printf("can't find count\n");
            exit(-1);
        }
        if (node->type == cJSON_String) {
            strcpy(dat.count, node->valuestring);
        }

        node = cJSON_GetObjectItem(json, "num1");
        if (node == NULL) {
            printf("can't find num1\n");
            exit(-1);
        }
        if (node->type == cJSON_Number) {
            dat.num1 = node->valuedouble;
        }

        node = cJSON_GetObjectItem(json, "num2");
        if (node == NULL) {
            printf("can't find num2\n");
            exit(-1);
        }
        if (node->type == cJSON_Number) {
            dat.num2 = node->valuedouble;
        }

        if (dat.type == 1) {
            num.sum = dat.num1 + dat.num2;
            printf("%f\n", num.sum);
        } else if (dat.type == 2) {
            num.sum = dat.num1 - dat.num2;
            printf("%f\n", num.sum);
        } else if (dat.type == 3) {
            num.sum = dat.num1 * dat.num2;
            printf("%f\n", num.sum);
        } else if (dat.type == 4) {
            num.sum = dat.num1 / dat.num2;
            printf("%f\n", num.sum);
        }

        json = cJSON_CreateObject();
        cJSON_AddItemToObject(json, "sum", cJSON_CreateNumber(num.sum));

        dest = cJSON_Print(json);

        ret = send(listenfd, dest, strlen(dest), 0);
        if (ret == -1) {
            perror("send");
            exit(-1);
        }
        cJSON_Delete(json);
    }

    close(listenfd);
    pthread_exit(NULL);
}

int main(int argc, const char *argv[]) {

    int sock = 0;
    int listenfd = 0;
    int ret = 0;

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        perror("sock");
        exit(-1);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(6661);
    addr.sin_addr.s_addr = inet_addr("192.168.198.128");

    ret = bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr));
    if (ret == -1) {
        perror("bind");
        exit(-1);
    }

    while (1) {
        listen(sock, 5);

        listenfd = accept(sock, NULL, NULL);
        if (listenfd == -1) {
            perror("accept");
            exit(-1);
        }

        pthread_t thread_id;
        pthread_create(&thread_id, NULL, fun, &listenfd);
        pthread_detach(thread_id); 
    }

    close(sock);

    return 0;
}
